package com.yunyao.common.utils;

import com.baomidou.mybatisplus.annotation.TableId;
import com.yunyao.common.core.validator.IgnorePadding;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ReflectUtil {
    static List<Class<?>> numbers = Arrays.asList(new Class<?>[]{
            Short.class,
            Integer.class,
            Long.class,
            Byte.class,
            Float.class,
            Double.class,
            Boolean.class
    });

    /**
     * 填充基础类型
     *
     * @param obj
     */
    public static void padding(Object obj) {
        Class<?> tClass = getActualityClass(obj);
        List<Field> fields =getAllFields(tClass);
        for (Field field : fields) {
            if (field.getAnnotation(IgnorePadding.class) != null)
                continue;
            if (field.getAnnotation(TableId.class) != null)
                continue;
            padding(field, obj, getDefaultValue(field.getType()));
        }
    }

    public static Object getDefaultValue(Class<?> tClass) {
        if (tClass.equals(Integer.class)) {
            return 0;
        } else if (tClass.equals(Long.class)) {
            return 0L;
        } else if (tClass.equals(Short.class)) {
            return (short) 0;
        } else if (tClass.equals(Byte.class)) {
            return (byte) 0;
        } else if (tClass.equals(Boolean.class)) {
            return Boolean.FALSE;
        } else if (tClass.equals(Float.class)) {
            return (float) 0;
        } else if (tClass.equals(Double.class)) {
            return (double) 0;
        } else if (tClass.equals(BigDecimal.class)) {
            return BigDecimal.valueOf(0);
        } else if (tClass.equals(BigInteger.class)) {
            return BigInteger.valueOf(0);
        }
        return null;
    }

    private static void padding(Field field, Object obj, Object value) {
        field.setAccessible(true);
        try {
            if (field.get(obj) == null) {
                field.set(obj, value);
            }
        } catch (IllegalAccessException e) {

        }
    }

    /**
     * 获取真实类
     *
     * @param obj
     * @return
     */
    public static Class<?> getActualityClass(Object obj) {
        if (obj == null)
            throw new NullPointerException("getActualityClass");
        Class<?> tClass = obj.getClass();
        if (tClass.isAnonymousClass()) {
            return tClass.getSuperclass();
        }
        return tClass;
    }

    public static List<Field> getAllFields(Class<?> tClass) {

        List<Field> fields = new ArrayList<>(List.of(tClass.getDeclaredFields()));
        Class<?> pClass = tClass;
        while (true) {
            pClass = pClass.getSuperclass();
            if (pClass.equals(Object.class))
                break;
            List<Field> pFields = List.of(pClass.getDeclaredFields());
            fields.addAll(pFields);
        }

        return fields;
    }

    public static Type[] getGenericType(Class<?> tClass) {
        ParameterizedType type = (ParameterizedType) (tClass.isInterface() ? tClass.getGenericInterfaces()[0] : tClass.getGenericSuperclass());
        return type.getActualTypeArguments();
    }


    public static Type getGenericType(Class<?> tClass, int index) {
        return getGenericType(tClass)[index];
    }

}
